package com.dsp.soundscape.server.jsf;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import java.util.logging.Logger;

import org.apache.commons.lang.WordUtils;

import com.dsp.soundscape.model.AlbumInfo;
import com.dsp.soundscape.model.VersionInfo;
import com.dsp.soundscape.server.SoundscapeLoader;

public class SoundscapeManager {
	private static Logger log = Logger.getLogger(SoundscapeManager.class.toString());
	
	private Map <String, AlbumInfo> albums;
	private Map <String, List<String>> albumsByArtist;
	private Map <String, List<String>> albumsByYear;
	
	private String latestYear;
	
	private String prefix;
	private boolean authenticated = false;
	
	private SoundscapeLoader loader;
	
	private String selectedArtist;
	private String selectedYear;
	
	public String generateId(AlbumInfo album) {
		return (album.getYear() + album.getArtist() + album.getAlbum()).replaceAll("[^a-zA-Z0-9]", "").toUpperCase();
	}
	
	public void setAuthenticated() {
		authenticated = true;
	}
	
	public boolean isAuthenticated() {
		return authenticated;
	}
	
	private List<AlbumInfo> currentView;
	
	public SoundscapeLoader getLoader() {
		return loader;
	}
	
	public void setLoader(SoundscapeLoader loader) {
		this.loader = loader;
		
		if (loader == null) {
			log.warning("Loader Was Not Injected");
		}
		
		albums = new TreeMap <String, AlbumInfo>();
		albumsByArtist = new TreeMap <String, List<String>>();
		albumsByYear = new TreeMap <String, List<String>>();
		
		for (String path : loader.getFolders()) {
			AlbumInfo album = new AlbumInfo();
			album.setFullpath(path);
			album.setId(generateId(album));
			
			if (album.getYear() != null && album.getArtist() != null) {
				album.setId(generateId(album));
				albums.put(album.getId(), album);
				
				List<String> artist = null;
				if (albumsByArtist.containsKey(album.getArtist().toLowerCase())) {
					artist = albumsByArtist.get(album.getArtist().toLowerCase());
				} else {
					artist = new ArrayList<String>();
					albumsByArtist.put(album.getArtist().toLowerCase(), artist);
				}
				artist.add(album.getId());
				
				List<String> year = null;
				if (albumsByYear.containsKey(album.getYear())) {
					year = albumsByYear.get(album.getYear());
				} else {
					year = new ArrayList<String>();
					albumsByYear.put(album.getYear(), year);
				}
				year.add(album.getId());
				
			} else {
				log.warning("Null Values, Ignoring Album: " + album);
			}

			Calendar today = Calendar.getInstance();
			int year = today.get(Calendar.YEAR);
			while (albumsByYear.size() > 0) {
				if (albumsByYear.containsKey(String.valueOf(year))) {
					latestYear = (String.valueOf(year));
					break;
				} else {
					year--;
				}
			}

			selectedYear = latestYear;
			currentView = getAlbumsByYear(latestYear);
		}
		
		prefix = loader.getPrefix();
	}
	
	public int getAlbumCount() {
		return albums.size();
	}

	public int getArtistCount() {
		return albumsByArtist.size();
	}
	
	public String getPrefix() {
		return prefix;
	}
	
	public String getSelectedArtist() {
		return selectedArtist;
	}

	public String getSelectedYear() {
		return selectedYear;
	}

	public List<AlbumInfo> randomize() {
		Random random = new Random(System.currentTimeMillis());
		ArrayList <AlbumInfo> albumList = new ArrayList<AlbumInfo>();
		List <String> artists = getArtists();
		List <String> selected = new ArrayList<String>();
		
		while (albumList.size() < 24) {
			int r1 = random.nextInt(artists.size());
			String artist = artists.get(r1);
			if (!selected.contains(artist.toLowerCase())) {
				List <String> albumKeys = albumsByArtist.get(artist.toLowerCase());
				int r2 = random.nextInt(albumKeys.size());
				albumList.add(albums.get(albumKeys.get(r2)));
				selected.add(artist.toLowerCase());
			}
		}
		
		Collections.sort(albumList);
		return albumList;
	}
	
//	public List<AlbumInfo> getAlbums() {
//		ArrayList <AlbumInfo> albumList = new ArrayList<AlbumInfo>();
//		albumList.addAll(albums.values());
//		Collections.sort(albumList);
//		return albumList;
//	}
	
	public List<String> getYears() {
		List <String> years = new ArrayList<String>();
		years.addAll(albumsByYear.keySet());
		return years;
	}
	
	public List<String> getArtists() {
		List <String> artists = new ArrayList<String>();
		for (String artist : albumsByArtist.keySet()) {
			artists.add(WordUtils.capitalizeFully(artist, new char[] {' ', '-', '.'}));
		}
		return artists;
	}
	
	public List<AlbumInfo> getAlbumsByArtist(String artist) {
		currentView = new ArrayList <AlbumInfo>();
		for (String id : albumsByArtist.get(artist.toLowerCase())) {
			currentView.add(albums.get(id));
		}
		
		selectedYear = null;
		selectedArtist = artist;
		
		Collections.sort(currentView);
		return currentView;
	}
	
	public List<AlbumInfo> getAlbumsByYear(String year) {
		currentView = new ArrayList <AlbumInfo>();
		for (String id : albumsByYear.get(year)) {
			currentView.add(albums.get(id));
		}
		
		selectedYear = year;
		selectedArtist = null;
		
		Collections.sort(currentView);
		return currentView;
	}
	
	public String getLatestYear() {
		return latestYear;
	}
	
	public List<AlbumInfo> getCurrentView() {
		return currentView;
	}
	
	public VersionInfo getVersion() {
		return loader.getVersion();
	}
	
	public AlbumInfo getAlbumInfo(String id) {
		AlbumInfo album = albums.get(id);
		if (!album.isPopulated()) {
			loader.populate(album);
		}
		return album;
	}
}